from abc import ABCMeta,abstractmethod,abstractproperty

class VersionConverterAPI(metaclass = ABCMeta):

    def __init__(self):
        self.version = 0

    @abstractmethod
    def convert_file_format(self):
        pass

    def __repr__(self):
        return  "name:{}, version:{}".format(self.__class__.__name__, self.version)

class VersionConverterBase(VersionConverterAPI):
    def __init__(self):
        super().__init__()
        self.version = 0
    
    def convert_file_format(self):
        print("None ==> v0")

class VersionConverter1(VersionConverterAPI):
    def __init__(self):
        super().__init__()
        self.version = 1
    
    def convert_file_format(self):
        print("v0 ==> v1")

class VersionConverter2(VersionConverterAPI):
    def __init__(self):
        super().__init__()
        self.version = 2
    
    def convert_file_format(self):
        print("v1 ==> v2")

class VersionConverter3(VersionConverterAPI):
    def __init__(self):
        super().__init__()
        self.version = 3
    
    def convert_file_format(self):
        print("v2 ==> v3")

class VersionConverter123(VersionConverterAPI):
    def __init__(self):
        super().__init__()
        self.version = 123
    
    def convert_file_format(self):
        print("v3 ==> v123")
###############################################################################


class LocalDataFileManager:
    def __init__(self):
        self.version_converts = [VersionConverterBase()]
        self.current_soft_version = 0

    def append_data_convert(self, data_convert):
        """
        向系统添加一个新的数据转换接口
        """
        self.version_converts.append(data_convert)

    def set_current_soft_version(self, soft_version):
        """
        设置当前软件的版本号
        """
        self.current_soft_version = soft_version

    def do_data_file_convert(self):
        """
        执行升级操作
        """
        current_data_file_version = self._read_version_from_current_data_file()

        # 查看一下是否需要升级
        if current_data_file_version == self.current_soft_version:
            return

        # 按照转换代码的版本号升序排序转换模块
        # 防止用户打乱版本号
        self._sort_data_converts_by_version()

        self._perform_convert(current_data_file_version, self.current_soft_version)

    def _sort_data_converts_by_version(self):
        self.version_converts.sort(key = lambda vc: vc.version)

    def _read_version_from_current_data_file(self):
        """
        从本地数据文件中，解析出目前本地数据文件的最新版本号
        """
        return 0

    def _get_array_index_by_convert_version(self, version):
        """
        获取对应版本的转换代码所在的数组索引
        """
        array_index = None
        for index, vc in enumerate(self.version_converts):
            if vc.version == version:
                array_index = index

        if array_index is None:
            raise RuntimeError("未找到对应于版本{} 的 数据转换模块".format(version))

        return array_index

        
    def _get_converts(self, start_version, end_version):
        """
        [start_version, end_version]
        返回在这个数据升级链中的转换函数
        """
        s_i = self._get_array_index_by_convert_version(start_version)
        e_i = self._get_array_index_by_convert_version(end_version)
        return self.version_converts[s_i+1:e_i+1]

    def _perform_convert(self, current_data_file_version, current_soft_version):
        for vc in self._get_converts(current_data_file_version, current_soft_version):
            vc.convert_file_format()



if __name__ == "__main__":
    
    LFM = LocalDataFileManager()
    LFM.append_data_convert(VersionConverter3())
    LFM.append_data_convert(VersionConverter123())
    LFM.append_data_convert(VersionConverter1())
    LFM.append_data_convert(VersionConverter2())
    LFM.set_current_soft_version(123)
    LFM.do_data_file_convert()    

